package ClassData;

import java.util.LinkedList;

import ClassData.Visitor.IVisitor;
import ClassData.Visitor.IVisitorElement;

/*
import DataFile.Structure_CP_ClassInfo;
import DataFile.Structure_CP_Table;
import DataFile.Structure_CP_UTF8Info;
import DataFile.Structure_ClassData;
import DataFile.Structure_ClassTable;
*/

public class ClassDataList extends LinkedList <ClassData> implements IVisitorElement {

	private static final long serialVersionUID = -1249019591936004266L;

	public void parseInheritance() {
	
	}

	/** Search for a ClassData by name.
	 * 
	 * @param ClassName Current ClassData name.
	 * @return Corresponding ClassData
	 */
	public ClassData findOnName(String ClassName)
	{
		int counter;
		ClassData tmpClass;
		
		for (counter=0;counter<this.size();counter++)
		{
			tmpClass=this.get(counter);
			if (tmpClass.getClassName().equals(ClassName))
				return(tmpClass);
		}
		
		// TODO Exception !!!!
		return(null);	
	}

	/**
	 * 
	 */
	public void parseDataList() {
		int classCounter; 	
		ClassData tmpClass;
		
		createArrayClasses();
		
		for (classCounter=0;classCounter<this.size();classCounter++) {
			tmpClass = get(classCounter);
			tmpClass.parseClassData();
		}
		
		for (classCounter=0;classCounter<this.size();classCounter++) {
			tmpClass = get(classCounter);
			
			if (!tmpClass.isIheritedDataSizeCalculated()) {
				parseDataSize(tmpClass);
			}
		}
	}

	/**
	 * 
	 * @param myClass
	 */
	public void parseDataSize(ClassData myClass) {
		//TODO Interfaces !!!!
		String SuperClassName;
		ClassData superClass;
		
		SuperClassName=myClass.getSuperClassName();
		if (SuperClassName=="") {
			myClass.setInheritedDataSize(0,0);
		} else {
			superClass=this.findOnName(SuperClassName);
			
			if (superClass!=null) {
				parseDataSize(superClass);
				myClass.setInheritedDataSize(superClass.getInheritedStaticDataSize()+superClass.getStaticDataSize()
											,superClass.getIinheritedInstanceDataSize()+superClass.getInstanceDataSize());
			} else {
				System.out.println("unknown class "+SuperClassName);
			}
		}
	}

/**
 * 
 */
private void createArrayClasses() {

	int classCounter;
	int constantCounter;
	int referencedClassIndex;
	
	ClassData tmpClassData;
	ConstantPool  classConstantPool;
	ConstantPoolClass_Info	referencedClassInfo;
	ConstantPoolUtf8_Info myUtf8Info;
	
	for (classCounter=0;classCounter< this.size();classCounter++) {
		tmpClassData=this.get(classCounter);
		
		classConstantPool=tmpClassData.getConstantPool();
		
		for (constantCounter=1;constantCounter<classConstantPool.size();constantCounter++) {
			if (classConstantPool.get(constantCounter).getClass().getName().equals(ConstantPoolClass_Info.class.getName())) {
				referencedClassInfo=(ConstantPoolClass_Info)classConstantPool.get(constantCounter);
				referencedClassIndex=referencedClassInfo.GetNameIndex();
				
				if (classConstantPool.get(referencedClassIndex).getClass().getName().equals(ConstantPoolUtf8_Info.class.getName())) {
					myUtf8Info=(ConstantPoolUtf8_Info) classConstantPool.get(referencedClassIndex);
					
					if (myUtf8Info.getString().startsWith("[")) {
						if (this.findOnName(myUtf8Info.getString())==null) {
							System.out.println("Inserting : " +myUtf8Info.getString());
							this.add(createArrayClass(myUtf8Info.getString()));
						}
					}	
				}
	/*
	 * 				if 	 (constantPoolTable.get(classIndex).getClass().getName().equals(Structure_CP_UTF8Info.class.getName()))
					{
					myUtf8Info=(Structure_CP_UTF8Info)constantPoolTable.get(classIndex);
					className=myUtf8Info.getString();
					if (className.startsWith("["))
						{
						System.out.println("Serching array "+ className);
						destinationClass=myClassTable.getClass(className);
						createArrayClass(className);
						}
			
	 */	
			}	
		}
	}
}
/*
private void createArrayClasses(Structure_ClassTable myClassTable)
{
	Structure_ClassData actualClass;	
	Structure_ClassData destinationClass;
	
	Structure_CP_Table constantPoolTable;
	int classCounter;
	int constantCounter;
	int classIndex;
	Structure_CP_ClassInfo myClassInfo;
	String className;

	Structure_CP_UTF8Info myUtf8Info;
	
	
	for (classCounter=0;classCounter<myClassTable.size();classCounter++)
		{
		actualClass=myClassTable.get(classCounter);
		constantPoolTable=actualClass.getConstantPoolTable();
		
		for (constantCounter=1;constantCounter<constantPoolTable.size()+1;constantCounter++)
			{
			if (constantPoolTable.get(constantCounter).getClass().getName().equals(Structure_CP_ClassInfo.class.getName()))
				{
				myClassInfo=(Structure_CP_ClassInfo)constantPoolTable.get(constantCounter);
			
				classIndex=myClassInfo.getClassNameIndex();
				
				if 	 (constantPoolTable.get(classIndex).getClass().getName().equals(Structure_CP_UTF8Info.class.getName()))
					{
					myUtf8Info=(Structure_CP_UTF8Info)constantPoolTable.get(classIndex);
					className=myUtf8Info.getString();
					if (className.startsWith("["))
						{
						System.out.println("Serching array "+ className);
						destinationClass=myClassTable.getClass(className);
						createArrayClass(className);
						}
//				className=constantPoolTable.getClassName(classIndex);
				
					 
					}
				}
			}
		
		
		}
		
}
*/

	/**
	 * 
	 */
	private ClassData createArrayClass(String className) {
		ClassData myClass;
		ConstantPool  myConstantPool;
		
		ConstantPoolClass_Info myClassInfo;
		ConstantPoolClass_Info superClassInfo;
		
		ConstantPoolUtf8_Info myClassName;
		ConstantPoolUtf8_Info supperClassName;
		
		myClassName = new ConstantPoolUtf8_Info(className);
		supperClassName = new ConstantPoolUtf8_Info("java/lang/Object");
		
		myClassInfo=new ConstantPoolClass_Info((short)2);
		superClassInfo=new ConstantPoolClass_Info((short)4);
		
		myConstantPool=new ConstantPool(4);
	
		myConstantPool.set(1, myClassInfo);
		myConstantPool.set(2, myClassName);
		myConstantPool.set(3, superClassInfo);
		myConstantPool.set(4, supperClassName);
		
		myClass=new ClassData(myConstantPool);
		
		return(myClass);
	}

	@Override
	public void receive_Visitor(IVisitor visitor) {
		visitor.visit_ClassDataList(this);
	}
	
}
